home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright 1992, 1993, 1994, Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
- * the contents of this file may not be disclosed to third parties, copied or
- * duplicated in any form, in whole or in part, without the prior written
- * permission of Silicon Graphics, Inc.
- *
- * RESTRICTED RIGHTS LEGEND:
- * Use, duplication or disclosure by the Government is subject to restrictions
- * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
- * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
- * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
- * rights reserved under the Copyright Laws of the United States.
- */
- /***
- closeup.c - image "magnifier" program
-
- Runs under the window manager.
- Closeup takes an rgb format image on the command line.
- Define XYZOOM as a simple way to demo independent x and y zoom.
- (Use 'make "VCDEFS=-DXYZOOM" closeup')
- -Rolf
-
- ***/
-
-
- #include <stdio.h>
- #include <math.h>
- #include <gl.h>
- #include <device.h>
- #include <image.h>
- #include "clang.h"
-
-
- void Setup();
- void HandleEvents();
- void SwapImage();
- void ReadImage();
- void WriteImage();
- void DrawIt();
- extern char *malloc();
- void ShrinkRow();
-
-
- #define PACK_RGB(rgb,r,g,b) { rgb = \
- (((u_char)b) << 16) | (((u_char)g) << 8) | ((u_char)r); }
- #define UNPACK_RGB(rgb,r,g,b) { \
- r = (rgb) & 0xff; \
- g = ((rgb) >> 8) & 0xff; \
- b = ((rgb) >> 16) & 0xff; }
-
- long shademode = FLAT ;
-
- char CmdName[] = "closeup";
- char UsageStr[] = "usage: closeup image-file";
-
- u_short ir[1280], ig[1280], ib[1280]; /* temps for reading the image file */
-
- typedef struct {
- int mousex, mousey; /* source location for magnify */
- int width, height; /* size in pixels of the image */
- long xorigin, yorigin; /* origin of the window */
- int boxwidth, boxheight; /* size of the zooming rectangle */
- float xzoom, yzoom; /* x and y zoom factors */
- Bool zoommode; /* set when zooming mode is enabled */
- RGBvalue *r, *g, *b; /* ptrs to the image */
- } StateInfo;
-
- StateInfo StateBlock;
- StateInfo *StatePtr = &StateBlock;
-
-
- void
- usage()
- {
- fprintf(stderr, "%s", UsageStr);
- exit(1);
- }
-
-
- /***
- Note: getopt code not used yet.
- ***/
- int
- main(argc, argv)
- char *argv[];
- int argc;
- {
- int c;
- extern int getopt(), optind;
- extern char * optarg;
-
- #ifdef NOTDEF
- while ((c = getopt(argc, argv, "u:")) != EOF) {
- switch (c) {
- default:
- usage();
- }
- }
- #endif
-
- if (argc != 2) {
- fprintf(stderr, "%s\n", UsageStr);
- exit(1);
- }
-
- figure_machine();
- {
- char *t, *strrchr();
- fprintf(stderr, "\n%s: Loading image. Please wait...",
- (t=strrchr(argv[0], '/')) != NULL ? t+1 : argv[0]);
- }
-
-
- Setup(argv[1], argv[0]);
-
- fprintf(stderr, " Done!\n");
-
- HandleEvents();
-
- /***
- clear the overlay planes before exiting
- ***/
- overlay(2);
- gconfig();
- drawmode(OVERDRAW);
- mapcolor(0, 0,0,0);
- mapcolor(1, 0,255,255);
- color(0);
- clear();
- drawmode(NORMALDRAW);
-
- return 0;
- }
-
-
- void
- Setup(imageName, progname)
- char *imageName;
- char *progname;
- {
- char line[100];
- int ixzoom, iyzoom;
-
- ReadImage(imageName);
- prefsize((long)StatePtr->width,(long)StatePtr->height);
- {
- char *t, *strrchr();
- winopen((t=strrchr(progname, '/')) != NULL ? t+1 : progname);
- }
- getorigin(&StatePtr->xorigin, &StatePtr->yorigin);
- RGBmode();
- doublebuffer();
- gconfig();
-
- RGBcolor(0, 0, 0);
- clear();
- swapbuffers();
- clear();
- zclear();
-
- overlay(2);
- gconfig();
- drawmode(OVERDRAW);
- mapcolor(0, 0,0,0);
- mapcolor(1, 0,255,255);
- color(0);
- clear();
- drawmode(NORMALDRAW);
-
- qdevice(LEFTMOUSE);
- qdevice(MIDDLEMOUSE);
- qdevice(RIGHTMOUSE);
- qdevice(INPUTCHANGE);
- qdevice(ESCKEY);
- qdevice(GKEY);
- qdevice(FKEY);
- qdevice(WINQUIT);
- qdevice(WINSHUT);
-
- StatePtr->xzoom = 5.0;
- StatePtr->yzoom = 5.0;
- StatePtr->zoommode = FALSE;
- ixzoom = (int) (StatePtr->xzoom + .5);
- iyzoom = (int) (StatePtr->yzoom + .5);
- StatePtr->boxwidth = StatePtr->width / ixzoom;
- StatePtr->boxheight = StatePtr->height / iyzoom;
-
- StatePtr->mousex = 0; /* doesn't really matter */
- StatePtr->mousey = 0;
-
- WriteImage();
-
- qdevice(TIMER1);
- noise(TIMER1, 1);
- }
-
-
- /***
- contains the main event loop.
- a interval timer is enabled while the window is attached.
- the timer is "paused" during time-consuming sequences
- to avoid timer events flooding the queue.
- ***/
- void
- HandleEvents()
- {
- short dev, val;
- int x, y;
- Bool attached = TRUE;
- Bool done = FALSE;
- #ifdef XYZOOM
- Bool xMode = TRUE;
- #endif
-
- /* check buttons for mode changes */
- while (dev = qread(&val)) {
-
- /* printf("closeup: event: dev=%d,val=%d\n", dev, val); */
-
- unqdevice(TIMER1);
-
- switch (dev) {
- case REDRAW:
- pushmatrix();
- drawmode(OVERDRAW);
- fullscrn();
- color(0);
- clear();
- endfullscrn();
- popmatrix();
- drawmode(NORMALDRAW);
- reshapeviewport();
- getorigin(&StatePtr->xorigin, &StatePtr->yorigin);
- WriteImage();
- break;
-
- case LEFTMOUSE:
- if (val) {
- #ifdef XYZOOM
- if (xMode) {
- if (StatePtr->xzoom < 31.5) StatePtr->xzoom += 1.0;
- }
- else {
- if (StatePtr->yzoom < 31.5) StatePtr->yzoom += 1.0;
- }
- #else
- if (StatePtr->xzoom < 31.5) StatePtr->xzoom += 1.0;
- if (StatePtr->yzoom < 31.5) StatePtr->yzoom += 1.0;
- #endif
- }
- break;
-
- case RIGHTMOUSE:
- if (val) {
- #ifdef XYZOOM
- if (xMode) {
- if (StatePtr->xzoom > 2.5) StatePtr->xzoom -= 1.0;
- }
- else {
- if (StatePtr->yzoom > 2.5) StatePtr->yzoom -= 1.0;
- }
- #else
- if (StatePtr->xzoom > 2.5) StatePtr->xzoom -= 1.0;
- if (StatePtr->yzoom > 2.5) StatePtr->yzoom -= 1.0;
- #endif
- }
- break;
-
- case INPUTCHANGE:
- /***
- Note: during development (GL & NeWS) there was trouble
- with this mechanism for attaching focus.
- just comment out this 'case' if the trouble recurs.
- ***/
- if (val) { /* mouse entered window */
- attached = TRUE;
- #ifdef XYZOOM
- xMode = (xMode) ? FALSE : TRUE;
- printf("closeup: updating %s axis\n", (xMode) ? "x":"y");
- #endif
- }
- else {
- attached = FALSE;
- }
- break;
-
- case GKEY:
- shademode = GOURAUD ;
- break ;
- case FKEY:
- shademode = FLAT ;
- break ;
- case ESCKEY:
- if (val) break;
- case WINQUIT:
- done = TRUE;
- break;
-
- default:
- break;
- }
-
-
- /***
- Compute size of zooming rectangle based on zoom factor.
- ***/
- {
- int ixzoom = (int) (StatePtr->xzoom + .5);
- int iyzoom = (int) (StatePtr->yzoom + .5);
- int boxwidth = StatePtr->width / ixzoom;
- int boxheight = StatePtr->height / iyzoom;
-
- StatePtr->boxwidth = boxwidth;
- StatePtr->boxheight = boxheight;
- }
-
- /***
- Mouse coords are mapped to the window and clamped
- to make the zooming rectangle stay inside the window.
- Note: the "+1" below avoids a visible glitch with rectcopy.
- ***/
- StatePtr->mousex = getvaluator(MOUSEX) - StatePtr->xorigin;
- StatePtr->mousey = getvaluator(MOUSEY) - StatePtr->yorigin;
- if (StatePtr->mousex < 0) {
- StatePtr->mousex = 0;
- }
- if (StatePtr->mousey <= 0) {
- StatePtr->mousey = 0 + 1;
- }
- if (StatePtr->mousex > StatePtr->width - StatePtr->boxwidth - 1) {
- StatePtr->mousex = StatePtr->width - StatePtr->boxwidth - 1;
- }
- if (StatePtr->mousey > StatePtr->height - StatePtr->boxheight - 1) {
- StatePtr->mousey = StatePtr->height - StatePtr->boxheight - 1;
- }
-
- /***
- switch the displayed buffer when mouse is down
- ***/
- if (getbutton(MIDDLEMOUSE)) {
- if (StatePtr->zoommode != TRUE) {
- StatePtr->zoommode = TRUE;
- }
- }
- else {
- if (StatePtr->zoommode != FALSE) {
- SwapImage(TRUE); /* copy image from z buffer to back buffer */
- swapbuffers();
- StatePtr->zoommode = FALSE;
- }
- }
-
- DrawIt(); /* this may do a swapbuffers() */
- if (attached) {
- qdevice(TIMER1);
- noise(TIMER1, 1);
- }
-
- if (done) break;
-
- } /* while... */
- }
-
-
- /***
- perform a rectcopy from the z buffer to the back buffer.
- adjust the destination size to fit the entire window.
- the zooming rectangle is bloated by one pixel (in x and in y)
- to ensure that the destination rectangle fills the window.
- (different zoom factors affect how well the dest rect fits)
- ***/
- void
- DrawIt()
- {
- int boxwidth = StatePtr->boxwidth;
- int boxheight = StatePtr->boxheight;
- static int oldmousex, oldmousey, oldboxwidth, oldboxheight;
- short junk;
-
- if (StatePtr->zoommode) {
- /* erase any old rectangle */
- drawmode(OVERDRAW);
- color(0);
- recti(oldmousex, oldmousey,
- oldmousex + oldboxwidth - 1, oldmousey + oldboxheight - 1 );
- drawmode(NORMALDRAW);
-
- readsource(SRC_ZBUFFER);
- if (shademode == FLAT) {
- rectzoom(StatePtr->xzoom, StatePtr->yzoom);
- rectcopy(StatePtr->mousex, StatePtr->mousey,
- StatePtr->mousex + boxwidth, StatePtr->mousey + boxheight,
- 0, 0 );
- }
- else
- /* Gouraud Shading */
- smoothcopy() ;
-
- gRGBcolor(&junk, &junk, &junk); /* hack to flush pipe */
- swapbuffers();
- }
- else {
- /* draw zooming rectangle in overlays when it changes */
- if ((StatePtr->mousex == oldmousex) &&
- (StatePtr->mousey == oldmousey) &&
- (boxwidth == oldboxwidth) &&
- (boxheight == oldboxheight) ) {
- ;
- }
- else {
- drawmode(OVERDRAW);
- color(0);
- recti(oldmousex, oldmousey,
- oldmousex + oldboxwidth - 1, oldmousey + oldboxheight - 1 );
- color(1);
- recti(StatePtr->mousex, StatePtr->mousey,
- StatePtr->mousex + boxwidth - 1,
- StatePtr->mousey + boxheight - 1 );
- oldmousex = StatePtr->mousex;
- oldmousey = StatePtr->mousey;
- oldboxwidth = boxwidth;
- oldboxheight = boxheight;
- drawmode(NORMALDRAW);
- }
- }
- }
-
- /* store pixels read for gouraud zoom */
- unsigned long *cbuf;
-
- makebuf() {
- /* compute source rect size based on window size and zoom factor */
- /* malloc a buffer based on the computed size */
- static size = 0;
- int msize;
- long xsrc,ysrc;
-
- int ixzoom = (int) (StatePtr->xzoom + .5);
- int iyzoom = (int) (StatePtr->yzoom + .5);
-
- /* Gouraud shading requires (n+1) points to gouraud shade (n) points */
- StatePtr->width++; /* n+1 */
- StatePtr->height++;
-
- StatePtr->boxwidth = StatePtr->width / ixzoom;
- StatePtr->boxheight =StatePtr->height / iyzoom;
-
- xsrc = (long)(StatePtr->width) ;
- ysrc = (long)(StatePtr->height) ;
- msize = (xsrc) * (ysrc);
- if (msize != size) {
- stepunit((int)ixzoom,(int)iyzoom);
- winconstraints();
- if (size > 0)
- free(cbuf);
- if ((cbuf=(unsigned long*)malloc(msize*4)) == 0) {
- fprintf(stderr," ERROR: can't malloc %d longs. abort.\n",msize);
- gexit() ;
- exit(1);
- }
- size = msize;
- }
- }
-
- smoothcopy() {
- /* read specified pixels, then draw gouraud shaded polygons */
- /* assume that matrix and viewport are set up 1-to-1 object-to-pixel */
- register x,y;
- register unsigned long *cp0,*cp1;
- register short *cp0s,*cp1s;
- long width;
- long height;
- long xfinal,yfinal;
- long vbuf[8];
- float fzoomx;
- float fzoomy;
- float fzoomz;
-
- makebuf() ;
-
- width = StatePtr->boxwidth ;
- height = StatePtr->boxheight ;
- xfinal = width ;
- yfinal = height ;
-
- lrectread(StatePtr->mousex,StatePtr->mousey,
- (StatePtr->mousex + width - 1),
- (StatePtr->mousey + height - 1),cbuf);
-
- pushmatrix();
- fzoomx = StatePtr->xzoom ;
- fzoomy = StatePtr->yzoom ;
- fzoomz = 0.0 ;
- scale((float)fzoomx,(float)fzoomy,(float)fzoomz);
- for (y=0; y<yfinal; y++) {
- vbuf[1] = vbuf[3] = y;
- vbuf[5] = vbuf[7] = y+1;
- cp0 = &cbuf[y * width];
- cp1 = &cbuf[(y+1) * width + 1];
- for (x=0; x<xfinal; x++) {
- vbuf[0] = vbuf[6] = x;
- vbuf[2] = vbuf[4] = x+1;
- bgnpolygon();
- cpack(*cp0++);
- v2i(vbuf);
- cpack(*cp0);
- v2i(vbuf+2);
- cpack(*cp1--);
- v2i(vbuf+4);
- cpack(*cp1++);
- v2i(vbuf+6);
- endpolygon();
- cp1 += 1;
- }
- }
- popmatrix();
- /* Restore Correct Values */
- --StatePtr->width ; /* n */
- --StatePtr->height ;
- }
-
-
- void
- ReadImage(name)
- char *name;
- {
- IMAGE *image;
- RGBvalue *r, *g, *b, *rp, *gp, *bp;
- int i, j, y, dx, dy;
-
- if ((image = iopen(name,"r")) == NULL) {
- fprintf(stderr, "%s: can't open image file %s\n", CmdName, name);
- exit(1);
- }
- if (image->zsize < 3) {
- fprintf(stderr, "%s: image file is not an rgb image", CmdName);
- exit(1);
- }
- dx = image->xsize;
- dy = image->ysize;
-
- r = (RGBvalue *) malloc(dx*dy*sizeof(RGBvalue));
- g = (RGBvalue *) malloc(dx*dy*sizeof(RGBvalue));
- b = (RGBvalue *) malloc(dx*dy*sizeof(RGBvalue));
-
- for (y=0, rp=r, gp=g, bp=b; y < dy; y++, rp+=dx, gp+=dx, bp+=dx) {
- getrow(image, ir, y, 0); ShrinkRow(dx, ir, rp);
- getrow(image, ig, y, 1); ShrinkRow(dx, ig, gp);
- getrow(image, ib, y, 2); ShrinkRow(dx, ib, bp);
- }
-
- /***
- save image parameters in global state (for WriteImage()).
- ***/
- StatePtr->r = r;
- StatePtr->g = g;
- StatePtr->b = b;
- StatePtr->width = dx;
- StatePtr->height = dy;
- }
-
-
- /***
- Assumes double buffer mode.
- ***/
- void
- Drawit()
- {
- RGBvalue *r, *g, *b, *rp, *gp, *bp;
- int y, dx, dy;
-
- /***
- get image parameters from global state.
- ***/
- r = StatePtr->r;
- g = StatePtr->g;
- b = StatePtr->b;
- dx = StatePtr->width;
- dy = StatePtr->height;
-
- /***
- write out image to the all buffers (especially the zbuffer).
- ***/
-
- #ifndef NOTDEF
- for (y=0, rp=r, gp=g, bp=b; y < dy; y++, rp+=dx, gp+=dx, bp+=dx) {
- cmov2i(0, y);
- writeRGB((short) dx, rp, gp, bp);
- }
- #else
- /***
- Note: this block of code doesn't work yet...
- ***/
- {
- int x, y;
- int *pixelp, pixelBuf[1280];
-
- rp = r; gp = g; bp = b;
- for (y = 0; y < dy; y++) {
- pixelp = pixelBuf;
- for (x = 0; x < dx; x++) {
- PACK_RGB(*pixelp, *rp, *gp, *bp);
- pixelp++, rp++, gp++, bp++;
- }
- (void) lrectwrite(0, y, dx - 1, y, pixelp);
- }
- }
- #endif
-
- }
-
- static enum {
- MACH_ECLIPSE,
- MACH_CLOVER2, /* Doesn't work on CLOVER1 */
- MACH_STAPUFT,
- MACH_VENICE,
- MACH_ELAN
- } machine;
-
- figure_machine()
- {
- char t[20];
- char mystring[60];
- static char ecl[] = "GL4DPI";
- static char cl2[] = "GL4DGT";
- static char stp[] = "GL4DVGX";
- static char ven[] = "GL4DRE";
- static char eln[] = "GL4DXG";
-
- gversion(t);
- if (strncmp(t, ecl, strlen(ecl)) == 0)
- machine = MACH_ECLIPSE;
- else if (strncmp(t, cl2, strlen(cl2)) == 0)
- machine = MACH_CLOVER2;
- else if (strncmp(t, stp, strlen(stp)) == 0)
- machine = MACH_STAPUFT;
- else if (strncmp(t, ven, strlen(ven)) == 0)
- machine = MACH_VENICE;
- else if (strncmp(t, eln, strlen(eln)) == 0)
- machine = MACH_ELAN;
- else {
- sprintf(mystring, "inform 'Sorry, closeup does not work on %s machines'", t);
- system(mystring);
- gexit();
- exit(1);
- }
- if ((getgdesc(GD_BITS_NORM_DBL_RED) + getgdesc(GD_BITS_NORM_DBL_GREEN) + getgdesc(GD_BITS_NORM_DBL_BLUE)) < 12) {
- sprintf(mystring, "Sorry, closeup needs at least 12 bitplanes to run.");
- system(mystring);
- gexit();
- exit(1);
- }
- }
-
- void
- WriteImage()
- {
- if (machine == MACH_ECLIPSE ||
- machine == MACH_ELAN)
- {
- zdraw(TRUE);
- Drawit();
- zdraw(FALSE);
- frontbuffer (TRUE);
- Drawit();
- }
- else
- {
- zdraw(TRUE);
- frontbuffer(TRUE);
- Drawit();
- zdraw(FALSE);
- }
- frontbuffer(FALSE);
- }
-
- /***
- Copy an image from (to) the zbuffer to (from) the back buffer.
- The image is the entire contents of the window.
- Assumes doublebuffer mode.
- ***/
- void
- SwapImage(fromz)
- Bool fromz; /* TRUE = copy from "z" to "back" buffer, FALSE = vice versa */
- {
- short junk;
-
- if (fromz) {
- readsource(SRC_ZBUFFER);
- frontbuffer(FALSE);
- backbuffer(TRUE);
- zdraw(FALSE);
- }
- else {
- fprintf(stderr, "SwapImage: doesn't work!\n");
- }
-
- rectzoom(1.0, 1.0);
- rectcopy(0, 0, StatePtr->width - 1, StatePtr->height - 1, 0, 0);
-
- gRGBcolor(&junk, &junk, &junk); /* hack to flush pipe */
- }
-
-
- /***
- Shrink an array of shorts into an array of bytes.
- ***/
- void
- ShrinkRow(cols, sp, bp)
- int cols;
- u_short *sp;
- RGBvalue *bp;
- {
- while (cols--) {
- *bp++ = *sp++;
- }
- }
-